package syntax;
import java.io.PrintStream;
import java.util.ArrayList;

import lexical.Scanner;
import astnode.AssignStmtNode;
import astnode.BinaryOperationNode;
import astnode.BranchStmtNode;
import astnode.CallNode;
import astnode.CaseNode;
import astnode.CompoundStmtNode;
import astnode.DeclarationNode;
import astnode.ExpressionNode;
import astnode.FunctionDeclarationNode;
import astnode.IDFactorNode;
import astnode.IDStmtNode;
import astnode.IfStmtNode;
import astnode.LiteralNode;
import astnode.LoopStmtNode;
import astnode.MarkerStmtNode;
import astnode.ParameterNode;
import astnode.ReturnStmtNode;
import astnode.StmtNode;
import astnode.UnitaryOperationNode;
import astnode.VariableDeclarationNode;
import astnode.VariableNode;

import common.LogPrinter;
import common.PrintVisitor;
import common.Token;
import common.TokenType;

public class Parser {
	private Scanner scanner = null;
	private TokenType lookahead = TokenType.ENDFILE;
	private int lookaheadValue = -1;
	private int lineNum = -1;
	private LogPrinter logPrinter = null;
	private PrintStream errPrinter = null;
	private PrintStream astPrinter = null;
	private ArrayList<String> spellingTable = null;
	private ArrayList< DeclarationNode > astRoot = new  ArrayList< DeclarationNode >();
	private boolean containsError = false;
	
	/*********************************************public functions begin************************************************************/
	public Parser(  Scanner scanner ,  LogPrinter p , PrintStream errPrinter, PrintStream astPrinter, ArrayList<String> spellingTable ){
		this.scanner = scanner;
		this.logPrinter = p;
		this.errPrinter = errPrinter;
		this.astPrinter = astPrinter;
		this.spellingTable = spellingTable;
	}
	
	/**
	 * @return if parser find errors
	 */
	public boolean containsErr(){
		return containsError;
	}
	
	/**
	 * print AST tree to ast printer
	 */
	public void printASTree( ){
		for( int i=0 ;i<getAstRoot().size() ; i++ ){
			getAstRoot().get(i).accept( new PrintVisitor(0, astPrinter , spellingTable ) );
		}
	}
	
	/*********************************************private function begin***********************************************************/
	
	private void getNextToken() throws Exception{
		Token t = scanner.nextToken();
		lookahead = t.getType();
		lookaheadValue = t.getValue();
		lineNum = scanner.getLineNum();
	}
	
	private void match( TokenType expected , SynchSet synch) throws Exception{		
		if( lookahead == expected ){
			logPrinter.printTrace("match "+expected, lineNum);
			getNextToken();
		}else{
			SynchError(synch,expected);
		}
		SynchCheck(synch);
	}		
	
	private void SynchCheck(SynchSet synch)throws Exception{
		if( lookahead == TokenType.ENDFILE ){
			return;
		}
		if(!synch.contain(lookahead)){
		    SynchError(synch, null);
		}
	}
	
	private void SynchError(SynchSet synch,TokenType expected)throws Exception{
		containsError = true;
		if( expected==null ){
			logPrinter.printTrace( String.format("Line %d: looking for a %s  but found %s instead",lineNum, synch , lookahead), lineNum );
			errPrinter.printf("Line %d: Unexpected %s\n", lineNum, lookahead);
		}else{
			logPrinter.printTrace("look for a " + lookahead +" is not in the SynchSet", lineNum);
			errPrinter.printf("Line %d: look for a %s  but found %s instead\n",lineNum, expected, lookahead);
		}		
		while(!synch.contain(lookahead)){
			getNextToken();	
			if(lookahead == TokenType.ENDFILE){
				break;
			}
		}
	}
		
	private boolean lookahead_In_FirstSet( NonterminalType non ){
		FirstSet firstSet = new FirstSet(non);
		return firstSet.contain(lookahead);
	}

	
	private void printEnterInfo(String functionName ){		
		logPrinter.printTrace( "Entering "+functionName, lineNum);
	}
	
	private void printLeaveInfo(String functionName ){
		logPrinter.printTrace( "Leaving "+functionName, lineNum);
	}
	
	/**
	 * begin analysis
	 * @throws Exception
	 */
	//1
	public void program() throws Exception{
		
		getNextToken();
		FirstSet set = new FirstSet( NonterminalType.declaration);
		SynchSet synch = new SynchSet();
		synch.union(NonterminalType.declaration);
		SynchCheck(synch);
		DeclarationNode node = new DeclarationNode( lineNum );
		node = declaration(node,synch);
		getAstRoot().add( node );
		while( set.contain( lookahead )){
			node = new DeclarationNode( lineNum );
			node = declaration(node,synch );
			getAstRoot().add( node );
			if( lookahead == TokenType.ENDFILE ){	
				break;
			}			
		}		
		scanner.printLastCode();
	}
	
	//2
     private DeclarationNode declaration( DeclarationNode node,SynchSet synch ) throws Exception{
		printEnterInfo( "declaration" );
		SynchSet synch_temp = new SynchSet();
		if( lookahead == TokenType.VOID ){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.ID);
			synch_temp.union(NonterminalType.funDecTail);
			node = new FunctionDeclarationNode( node );
			node.setType( TokenType.VOID );
			match( TokenType.VOID , synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.funDecTail);
			node.setIdentifier( lookaheadValue );
			match( TokenType.ID , synch_temp);
			funDecTail((FunctionDeclarationNode) node,synch);
		}
        else if(lookahead_In_FirstSet(NonterminalType.nonVoidSpecifier)){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.ID);
			synch_temp.union(NonterminalType.decTail);
			nonVoidSpecifier(node,synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.decTail);
			node.setIdentifier( lookaheadValue );
			match(TokenType.ID,synch_temp);
			node = decTail(node,synch);
		}
		else{
			SynchError(synch,null);
		}
		printLeaveInfo( "declaration" );

		return node;
        }
	
	//3
  private void nonVoidSpecifier(DeclarationNode node,SynchSet synch) throws Exception {
		printEnterInfo( "nonVoidSpecifier" );
		if( lookahead == TokenType.INT ){
			node.setType( TokenType.INT );
			match(  TokenType.INT , synch);
		}else if(lookahead == TokenType.BOOL){
			node.setType( TokenType.BOOL );
			match( TokenType.BOOL , synch);
		}else{
			SynchError(synch,null);
		}
	}
	
	//4
	private DeclarationNode decTail(DeclarationNode node,SynchSet synch) throws Exception {
		printEnterInfo( "decTail" );
		if( lookahead_In_FirstSet( NonterminalType.varDecTail )){
			node = new VariableDeclarationNode(node);
			varDecTail((VariableDeclarationNode)node,synch);

		}else if(lookahead_In_FirstSet(NonterminalType.funDecTail)){
			node = new FunctionDeclarationNode(node);
			funDecTail((FunctionDeclarationNode) node ,synch);
		}else{
			SynchError(synch,null);
		}
		printLeaveInfo( "decTail" );		
		return node;
	}
	
	//5

	private void varDecTail( VariableDeclarationNode node,SynchSet synch) throws Exception {
		printEnterInfo( "varDecTail" );
		SynchSet synch_temp = new SynchSet();
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.addTerminal(TokenType.LSQR);
		synch_temp.addTerminal(TokenType.COMMA);
		synch_temp.addTerminal(TokenType.SEMI);
		SynchCheck(synch_temp);
		if( lookahead == TokenType.LSQR ){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.addExp);
			synch_temp.addTerminal(TokenType.RSQR);
			synch_temp.addTerminal(TokenType.COMMA);
			synch_temp.addTerminal(TokenType.SEMI);	
			match( TokenType.LSQR , synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.addExp);
			synch_temp.addTerminal(TokenType.RSQR);
			synch_temp.addTerminal(TokenType.COMMA);
			synch_temp.addTerminal(TokenType.SEMI);
			ExpressionNode expNode = new ExpressionNode(lineNum);
			expNode = addExp( expNode,synch_temp );
			node.setSize(expNode);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.COMMA);
			synch_temp.addTerminal(TokenType.SEMI);
			match( TokenType.RSQR , synch_temp);
		}
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.addTerminal(TokenType.COMMA);
		synch_temp.addTerminal(TokenType.SEMI);
		SynchCheck(synch_temp);
		while( lookahead==TokenType.COMMA ){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.COMMA);
			synch_temp.union(NonterminalType.varName);
			synch_temp.addTerminal(TokenType.SEMI);
			match(TokenType.COMMA, synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.COMMA);
			synch_temp.addTerminal(TokenType.SEMI);
			VariableDeclarationNode follow = new VariableDeclarationNode(lineNum);
			follow.setType( node.getType() );
			varName(follow,synch_temp);
			follow.setType( node.getType() );
			node.addFollowVariableDeclaration( follow );
		}
		match(TokenType.SEMI,synch);
		printLeaveInfo( "varDecTail" );
	}

	//6
	private VariableDeclarationNode varName(VariableDeclarationNode node,SynchSet synch ) throws Exception {
		printEnterInfo( "varName" );
		SynchSet synch_temp = new SynchSet();
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.addTerminal(TokenType.LSQR);
		node.setIdentifier( lookaheadValue );
		match(TokenType.ID,synch_temp);
		SynchCheck(synch_temp);	
		if( lookahead == TokenType.LSQR ){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.addExp);
			synch_temp.addTerminal(TokenType.RSQR);
			match(TokenType.LSQR ,synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.RSQR);
			ExpressionNode expNode = new ExpressionNode(lineNum);
			expNode = addExp(expNode,synch_temp);
			node.setSize( expNode );
			match( TokenType.RSQR,synch );
		}
		printLeaveInfo( "varName" );
		return node;
	}
	
	//7
	private void funDecTail( FunctionDeclarationNode node ,SynchSet synch) throws Exception {
		printEnterInfo( "funDecTail" );
		SynchSet synch_temp = new SynchSet();
		    synch_temp.clear();
		    synch_temp.union(synch);
		    synch_temp.union(NonterminalType.params);
		    synch_temp.addTerminal(TokenType.RPAREN);
		    synch_temp.union(NonterminalType.compoundStmt);
			match(TokenType.LPAREN,synch_temp);
			synch_temp.clear();
		    synch_temp.union(synch);
		    synch_temp.addTerminal(TokenType.RPAREN);
		    synch_temp.union(NonterminalType.compoundStmt);
		    //set params in node
			params(node,synch_temp);
			synch_temp.clear();
		    synch_temp.union(synch);
		    synch_temp.union(NonterminalType.compoundStmt);
			match(TokenType.RPAREN,synch_temp);
			CompoundStmtNode comStmtNode = new CompoundStmtNode( lineNum );
			compoundStmt(comStmtNode,synch);
			node.setComspond(comStmtNode);
		printLeaveInfo( "funDecTail" );
	}
	
	//8
		private void params( FunctionDeclarationNode node ,SynchSet synch) throws Exception {
			printEnterInfo( "params" );
			SynchSet synch_temp = new SynchSet();
			if(lookahead_In_FirstSet(NonterminalType.param))
			{
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.COMMA);
			//add first param to FunctionDeclaration
			ParameterNode paramNode = new ParameterNode( lineNum );
			param(paramNode,synch_temp);
			node.addParameter(paramNode);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.COMMA);
			SynchCheck(synch_temp);
				while( lookahead== TokenType.COMMA ){
					synch_temp.clear();
					synch_temp.union(synch);
					synch_temp.addTerminal(TokenType.COMMA);
					synch_temp.union(NonterminalType.param);
					match(TokenType.COMMA,synch_temp);
					synch_temp.clear();
					synch_temp.union(synch);
					synch_temp.addTerminal(TokenType.COMMA);
					paramNode = new ParameterNode( lineNum );
					param(paramNode,synch_temp);
					node.addParameter(paramNode);
					
				}
			}
			else if(lookahead==TokenType.VOID)
			{
				match(TokenType.VOID,synch);
			}
			else
			{
				SynchError(synch,null);
			}
			printLeaveInfo( "params" );
		}

		//9

		private void param( ParameterNode node,SynchSet synch ) throws Exception {
			printEnterInfo( "param" );
			SynchSet synch_temp = new SynchSet();
			if( lookahead==TokenType.REF ){
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.nonVoidSpecifier);
				synch_temp.addTerminal(TokenType.ID);
				//set ref
				node.setRef( true );
				match(TokenType.REF,synch_temp);
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.ID);
				//set Specifier
				nonVoidSpecifier(node,synch_temp);
				node.setIdentifier(lookaheadValue);
				match(TokenType.ID,synch);
			}else if(lookahead_In_FirstSet(NonterminalType.nonVoidSpecifier))
			{
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.ID);
				synch_temp.addTerminal(TokenType.LSQR);
				//set Specifier
				nonVoidSpecifier(node,synch_temp);
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.LSQR);
				//set ID
				node.setIdentifier(lookaheadValue);
				match(TokenType.ID,synch_temp);
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.LSQR);
				SynchCheck(synch_temp);
				if(lookahead== TokenType.LSQR){
					synch_temp.clear();
					synch_temp.union(synch);
					synch_temp.addTerminal(TokenType.RSQR);
					//Now determine param is array
					node.setArray(true);
					match(TokenType.LSQR,synch_temp);					
					match(TokenType.RSQR,synch);
					}
			}
			else{
				SynchError(synch,null);
			}
			printLeaveInfo( "param" );
		}
	
		//10
		private StmtNode statement(SynchSet synch ) throws Exception {
			printEnterInfo( "statement" );
			StmtNode node;
			if( lookahead_In_FirstSet( NonterminalType.idStmt )){
				node = idStmt( new IDStmtNode( lineNum ) ,synch);
			}
			else if( new FirstSet( NonterminalType.compoundStmt ).contain( lookahead ) ){
				node = new CompoundStmtNode( lineNum );
				compoundStmt((CompoundStmtNode) node,synch);
			}else if( new FirstSet( NonterminalType.ifStmt ).contain( lookahead ) ){
				node = new IfStmtNode( lineNum );
				ifStmt( (IfStmtNode) node ,synch);
			}else if( new FirstSet( NonterminalType.loopStmt ).contain( lookahead ) ){
				node = new LoopStmtNode( lineNum );
				//set attributes
				loopStmt( (LoopStmtNode) node,synch );
			}else if( new FirstSet( NonterminalType.exitStmt ).contain( lookahead ) ){
				node = new MarkerStmtNode( lineNum );
				exitStmt( (MarkerStmtNode) node,synch);
			}else if( new FirstSet( NonterminalType.continueStmt ).contain( lookahead ) ){
				node = new MarkerStmtNode( lineNum );
				continueStmt( (MarkerStmtNode) node ,synch);
			}else if( new FirstSet( NonterminalType.returnStmt ).contain( lookahead ) ){
				node = new ReturnStmtNode( lineNum );
				returnStmt( (ReturnStmtNode) node,synch);
			}else if( new FirstSet( NonterminalType.nullStmt ).contain( lookahead ) ){
				node = new MarkerStmtNode( lineNum );
				nullStmt((MarkerStmtNode) node,synch);
			}else if( new FirstSet(NonterminalType.branchStmt).contain(lookahead)){
				node = new BranchStmtNode( lineNum );
				branchStmt( (BranchStmtNode) node,synch);
			}
			else{
				node = null;
				SynchError(synch,null);
			}
			printLeaveInfo( "statement" );
			return node;
		}
		
		//11
		private StmtNode idStmt( IDStmtNode node,SynchSet synch) throws Exception {
			printEnterInfo( "idStmt" );
			SynchSet synch_temp = new SynchSet();
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.idStmtTail);
			//meet ID
			node.setIdentifier(lookaheadValue);
			match(TokenType.ID,synch_temp);
			StmtNode stmt = idStmtTail( node ,synch);			
			printLeaveInfo( "idStmt" );
			return stmt;
		}
		
		//12
		private StmtNode idStmtTail(IDStmtNode idStmtNode,SynchSet synch) throws Exception {
			printEnterInfo( "idStmtTail" );
			StmtNode stmt = null;
			if( lookahead_In_FirstSet( NonterminalType.assignStmtTail )){
				stmt = new AssignStmtNode( idStmtNode ); 
				assignStmtTail((AssignStmtNode) stmt ,synch);
			}else if( lookahead_In_FirstSet( NonterminalType.callStmtTail )){
				stmt = new CallNode( idStmtNode ); 
				callStmtTail( (CallNode) stmt,synch );
			}
			else{
				SynchError(synch,null);
			}
			printLeaveInfo( "idStmtTail" );
			return stmt;
		}
		
		//13
			private void assignStmtTail( AssignStmtNode node,SynchSet synch ) throws Exception {
				printEnterInfo( "assignStmtTail" );
				SynchSet synch_temp = new SynchSet();
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.LSQR);
				synch_temp.addTerminal(TokenType.ASSIGN);
				synch_temp.union(NonterminalType.expression);
				synch_temp.addTerminal(TokenType.SEMI);
				SynchCheck(synch_temp);
				if( lookahead == TokenType.LSQR ){
					synch_temp.clear();
					synch_temp.union(synch);
					synch_temp.union(NonterminalType.addExp);
					synch_temp.addTerminal(TokenType.RSQR);
					synch_temp.addTerminal(TokenType.ASSIGN);
					synch_temp.union(NonterminalType.expression);
					synch_temp.addTerminal(TokenType.SEMI);
					match( TokenType.LSQR,synch_temp);
					synch_temp.clear();
					synch_temp.union(synch);
					synch_temp.addTerminal(TokenType.RSQR);
					synch_temp.addTerminal(TokenType.ASSIGN);
					synch_temp.union(NonterminalType.expression);
					synch_temp.addTerminal(TokenType.SEMI);
					ExpressionNode exp = addExp( new ExpressionNode( lineNum ),synch_temp );
					node.setIndex( exp );
					synch_temp.clear();
					synch_temp.union(synch);
					synch_temp.addTerminal(TokenType.ASSIGN);
					synch_temp.union(NonterminalType.expression);
					synch_temp.addTerminal(TokenType.SEMI);
					match( TokenType.RSQR,synch_temp);
 			}
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.expression);
				synch_temp.addTerminal(TokenType.SEMI);
				match( TokenType.ASSIGN ,synch_temp);
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.SEMI);
				ExpressionNode exp = expression ( new ExpressionNode( lineNum ) ,synch_temp) ;
				node.setRightvalue(exp);
				match( TokenType.SEMI,synch );
				printLeaveInfo( "assignStmtTail" );
			}

		//14
		private void callStmtTail( CallNode node,SynchSet synch) throws Exception {
			printEnterInfo( "callStmtTail" );
			SynchSet synch_temp = new SynchSet();
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.SEMI);
			callTail(node,synch_temp);
			match(TokenType.SEMI,synch);		
		printLeaveInfo( "callStmtTail" );
		}
		
	//15
	private void callTail( CallNode node ,SynchSet synch) throws Exception {
		printEnterInfo( "callTail" );
		SynchSet synch_temp = new SynchSet();
		    synch_temp.clear();
		    synch_temp.union(synch);
			synch_temp.union(NonterminalType.arguments);
			synch_temp.addTerminal(TokenType.RPAREN);
			match(TokenType.LPAREN,synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.arguments);
			synch_temp.addTerminal(TokenType.RPAREN);
			SynchCheck(synch_temp);
			if( lookahead_In_FirstSet( NonterminalType.arguments )){
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.RPAREN);
				arguments(node,synch_temp);
			}
			match( TokenType.RPAREN ,synch);	
			printLeaveInfo( "callTail" );
	}
	
	//16

	private void arguments( CallNode node ,SynchSet synch) throws Exception {
		printEnterInfo( "arguments" );
		SynchSet synch_temp = new SynchSet();
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.addTerminal(TokenType.COMMA);
		ExpressionNode exp = expression( new ExpressionNode( lineNum ), synch_temp);
		node.addArguements( exp );
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.addTerminal(TokenType.COMMA);
		SynchCheck(synch_temp);
		while( lookahead==TokenType.COMMA ){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.COMMA);
			synch_temp.union(NonterminalType.expression);
			match(TokenType.COMMA,synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.COMMA);
			exp = expression( new ExpressionNode( lineNum ) ,synch_temp);
			node.addArguements( exp );
		}	
		printLeaveInfo( "arguments" );
	}
	
	//17
	private void compoundStmt( CompoundStmtNode comNode ,SynchSet synch) throws Exception {
		printEnterInfo( "compoundStmt" );
		SynchSet synch_temp = new SynchSet();
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.union(NonterminalType.nonVoidSpecifier);
		synch_temp.union(NonterminalType.statement);
		synch_temp.addTerminal(TokenType.RCRLY);
			match( TokenType.LCRLY ,synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.statement);
			synch_temp.addTerminal(TokenType.RCRLY);
			synch_temp.union(NonterminalType.nonVoidSpecifier);
			SynchCheck(synch_temp);
			while( new FirstSet( NonterminalType.nonVoidSpecifier ).contain( lookahead ) ){
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.nonVoidSpecifier);
				synch_temp.addTerminal(TokenType.ID);
				synch_temp.union(NonterminalType.varDecTail);
				synch_temp.union(NonterminalType.statement);
				synch_temp.addTerminal(TokenType.RCRLY);
				VariableDeclarationNode node = new VariableDeclarationNode( lineNum );
				nonVoidSpecifier( node ,synch_temp );
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.nonVoidSpecifier);
				synch_temp.union(NonterminalType.varDecTail);
				synch_temp.union(NonterminalType.statement);
				synch_temp.addTerminal(TokenType.RCRLY);
				node.setIdentifier(lookaheadValue);
				match(TokenType.ID,synch_temp);
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.RCRLY);
				synch_temp.union(NonterminalType.statement);
				synch_temp.union(NonterminalType.nonVoidSpecifier);
				varDecTail( node,synch_temp);
				comNode.addDeclarationNode(node);
			}
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.statement);
			synch_temp.addTerminal(TokenType.RCRLY);
			StmtNode stmt = statement(synch_temp);
			comNode.addStmtNode(stmt);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.RCRLY);
			synch_temp.union(NonterminalType.statement);
			SynchCheck(synch_temp);
			while( lookahead_In_FirstSet(NonterminalType.statement) ){
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.RCRLY);
				synch_temp.union(NonterminalType.statement);
				stmt = statement(synch_temp);
				comNode.addStmtNode(stmt);
			}
			match(TokenType.RCRLY,synch);				
		printLeaveInfo( "compoundStmt" );
	}
		
		//18
			private void ifStmt( IfStmtNode node,SynchSet synch ) throws Exception {
				printEnterInfo( "ifStmt" );
				SynchSet synch_temp = new SynchSet();
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.LPAREN);
				synch_temp.union(NonterminalType.expression);
				synch_temp.addTerminal(TokenType.RPAREN);
				synch_temp.union(NonterminalType.statement);
				synch_temp.addTerminal(TokenType.ELSE);
				match( TokenType.IF,synch_temp );
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.expression);
				synch_temp.addTerminal(TokenType.RPAREN);
				synch_temp.union(NonterminalType.statement);
				synch_temp.addTerminal(TokenType.ELSE);
				match( TokenType.LPAREN,synch_temp );
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.RPAREN);
				synch_temp.union(NonterminalType.statement);
				synch_temp.addTerminal(TokenType.ELSE);
				//meet exp
				ExpressionNode exp = expression( new ExpressionNode( lineNum ) ,synch_temp);
				node.setCondition( exp );
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.statement);
				synch_temp.addTerminal(TokenType.ELSE);
				match( TokenType.RPAREN,synch_temp );
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.ELSE);
				StmtNode stmt = statement(synch_temp);
				node.setTureBody(stmt);
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.ELSE);
				SynchCheck(synch_temp);
				if( lookahead == TokenType.ELSE ){
					synch_temp.clear();
					synch_temp.union(synch);
					synch_temp.union(NonterminalType.statement);
					match( TokenType.ELSE ,synch_temp);
					stmt = statement(synch);
					node.setElseBody( stmt );
				}
				printLeaveInfo( "ifStmt" );
			}

		//19
	private void loopStmt(LoopStmtNode node,SynchSet synch) throws Exception {
			printEnterInfo( "loopStmt" );
			SynchSet synch_temp = new SynchSet();
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.statement);
			synch_temp.addTerminal(TokenType.END);
			synch_temp.addTerminal(TokenType.SEMI);
			match( TokenType.LOOP ,synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.statement);
			synch_temp.addTerminal(TokenType.END);
			synch_temp.addTerminal(TokenType.SEMI);
			StmtNode stmt = statement(synch_temp);
			node.addStatement( stmt );
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.statement);
			synch_temp.addTerminal(TokenType.END);
			synch_temp.addTerminal(TokenType.SEMI);
			SynchCheck(synch_temp);
			while( lookahead_In_FirstSet( NonterminalType.statement ) ){
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.statement);
				synch_temp.addTerminal(TokenType.END);
				synch_temp.addTerminal(TokenType.SEMI);
				stmt = statement(synch_temp);
				node.addStatement( stmt );
		}
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.SEMI);
			match( TokenType.END,synch_temp );
			match( TokenType.SEMI,synch );		
			printLeaveInfo( "loopStmt" );
		}
		
		//20
			private void exitStmt( MarkerStmtNode node,SynchSet synch) throws Exception {
				printEnterInfo( "exitStmt" );
				SynchSet synch_temp = new SynchSet();
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.SEMI);
				node.setType( TokenType.EXIT );
				match( TokenType.EXIT ,synch_temp );
				match( TokenType.SEMI ,synch);		
				printLeaveInfo( "exitStmt" );				
				
			}
		
		//21
			private void continueStmt(  MarkerStmtNode node ,SynchSet synch) throws Exception {
				printEnterInfo( "continueStmt" );
				SynchSet synch_temp = new SynchSet();
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.addTerminal(TokenType.SEMI);
				//set node type 
				node.setType( TokenType.CONTINUE );
				match( TokenType.CONTINUE,synch_temp);
				match( TokenType.SEMI ,synch);
				printLeaveInfo( "continueStmt" );				
			}


	//22
	private void returnStmt( ReturnStmtNode node ,SynchSet synch) throws Exception {
		printEnterInfo( "returnStmt" );
		SynchSet synch_temp = new SynchSet();
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.union(NonterminalType.expression);
		synch_temp.addTerminal(TokenType.SEMI);		
		match( TokenType.RETURN ,synch_temp);
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.union(NonterminalType.expression);
		synch_temp.addTerminal(TokenType.SEMI);			
		SynchCheck(synch_temp);
		if( new FirstSet( NonterminalType.expression ).contain( lookahead ) ){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.SEMI);
 		ExpressionNode exp = expression(  new ExpressionNode( lineNum ),synch_temp );
		node.setValue( exp );
		}
		match( TokenType.SEMI ,synch);
		printLeaveInfo( "returnStmt" );
	}
	
	//23
	private void nullStmt( MarkerStmtNode node,SynchSet synch ) throws Exception {
		printEnterInfo( "nullStmt" );
		node.setType( TokenType.SEMI );
		match( TokenType.SEMI ,synch);		
		printLeaveInfo( "nullStmt" );
	}
	
	//24

	private void branchStmt( BranchStmtNode node,SynchSet synch ) throws Exception {
		printEnterInfo( "branchStmt" );
		SynchSet synch_temp = new SynchSet();
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.addTerminal(TokenType.LPAREN);
		synch_temp.union(NonterminalType.addExp);
		synch_temp.addTerminal(TokenType.RPAREN);
		synch_temp.union(NonterminalType.caseStmt);
		synch_temp.addTerminal(TokenType.END);
		synch_temp.addTerminal(TokenType.SEMI);
		match( TokenType.BRANCH ,synch_temp);
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.union(NonterminalType.addExp);
		synch_temp.addTerminal(TokenType.RPAREN);
		synch_temp.union(NonterminalType.caseStmt);
		synch_temp.addTerminal(TokenType.END);
		synch_temp.addTerminal(TokenType.SEMI);
		match( TokenType.LPAREN ,synch_temp);
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.addTerminal(TokenType.RPAREN);
		synch_temp.union(NonterminalType.caseStmt);
		synch_temp.addTerminal(TokenType.END);
		synch_temp.addTerminal(TokenType.SEMI);
		ExpressionNode exp = addExp( new ExpressionNode( lineNum ) ,synch_temp);		
		node.setExp(exp);
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.union(NonterminalType.caseStmt);
		synch_temp.addTerminal(TokenType.END);
		synch_temp.addTerminal(TokenType.SEMI);
		match( TokenType.RPAREN ,synch_temp);
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.union(NonterminalType.caseStmt);
		synch_temp.addTerminal(TokenType.END);
		synch_temp.addTerminal(TokenType.SEMI);
		CaseNode caseNode = new CaseNode( lineNum );
		caseStmt(caseNode,synch_temp);
		node.addCaseNode(caseNode);
		synch_temp.union(NonterminalType.caseStmt);
		SynchCheck(synch_temp);
		while( new FirstSet( NonterminalType.caseStmt ).contain( lookahead )){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.caseStmt);
			synch_temp.addTerminal(TokenType.END);
			synch_temp.addTerminal(TokenType.SEMI);
			caseNode = new CaseNode( lineNum );
			caseStmt(caseNode,synch_temp);
			node.addCaseNode(caseNode);
		}
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.addTerminal(TokenType.SEMI);
		match( TokenType.END ,synch_temp);
		match( TokenType.SEMI,synch );
		printLeaveInfo( "branchStmt" );
	}

	//25
	private void caseStmt(CaseNode caseNode,SynchSet synch) throws Exception{
		printEnterInfo( "caseStmt" );
		SynchSet synch_temp = new SynchSet();
		if( lookahead==TokenType.CASE ){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.NUM);
			synch_temp.addTerminal(TokenType.COLON);
			synch_temp.union(NonterminalType.statement);
			match(TokenType.CASE,synch_temp);
			caseNode.setNumber( lookaheadValue );
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.COLON);
			synch_temp.union(NonterminalType.statement);
			caseNode.setNumber( lookaheadValue );
			match(TokenType.NUM,synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.statement);
			match( TokenType.COLON,synch_temp);
			StmtNode stmt = statement(synch);
			caseNode.setStmt(stmt);
		}else if(lookahead==TokenType.DEFAULT){
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.COLON);
			synch_temp.union(NonterminalType.statement);
			match( TokenType.DEFAULT,synch_temp );
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.statement);
			match( TokenType.COLON,synch_temp);
			StmtNode stmt = statement(synch);
			caseNode.setStmt(stmt);
		}
		else{
			SynchError(synch,null);
		}
		printLeaveInfo( "caseStmt" );
	}
	
	//26
		private ExpressionNode expression( ExpressionNode node,SynchSet synch ) throws Exception {
			printEnterInfo( "expression" );
			SynchSet synch_temp = new SynchSet();
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.relop);
			//suppose it's just single operand
			node = addExp( new ExpressionNode( lineNum ) ,synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.relop);
			SynchCheck(synch_temp);
			if( new FirstSet(NonterminalType.relop).contain( lookahead ) ){
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.addExp);
				BinaryOperationNode binOp = new BinaryOperationNode( lineNum );
				binOp.setLeftExp( node );
				relop(binOp,synch_temp);
				ExpressionNode exp = addExp( new ExpressionNode( lineNum ),synch );
				binOp.setRightExp( exp );
				node = binOp;
				}
			printLeaveInfo( "expression" );
			return node;
		}
	
	//27
		
	private ExpressionNode addExp(ExpressionNode expNode,SynchSet synch) throws Exception {
		printEnterInfo( "addExp" );
        SynchSet synch_temp = new SynchSet();
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.union(NonterminalType.uminus);
		synch_temp.union(NonterminalType.term);
		synch_temp.union(NonterminalType.addop);
		SynchCheck(synch_temp);
		UnitaryOperationNode unitary = null;
		if( lookahead_In_FirstSet( NonterminalType.uminus )){
			unitary = new UnitaryOperationNode( lineNum );
			uminus( unitary,synch_temp);
		}
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.union(NonterminalType.addop);
		expNode = term( new ExpressionNode( lineNum ),synch_temp );
		if( unitary!=null ){
			unitary.setOperand(expNode);
			expNode = unitary;
		}
		BinaryOperationNode binOpr = null;
		synch_temp.clear();
		synch_temp.union(synch);
		synch_temp.union(NonterminalType.addop);
		SynchCheck(synch_temp);
		while( lookahead_In_FirstSet( NonterminalType.addop )){
			if( binOpr != null ){
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.addop);
				synch_temp.union(NonterminalType.term);
				//meet binOpr more than once
				//this time binOpr is the left operand of newBinOpr , term is right
				BinaryOperationNode newBinOpr = new BinaryOperationNode( lineNum );
				addop( newBinOpr,synch_temp );
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.addop);
				newBinOpr.setLeftExp( binOpr );
				ExpressionNode right = term( new ExpressionNode( lineNum ) ,synch_temp);
				newBinOpr.setRightExp(right);
				expNode = newBinOpr;
			}else{
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.addop);
				synch_temp.union(NonterminalType.term);
				//first meet binOpr
				binOpr = new BinaryOperationNode( lineNum );
				addop( binOpr,synch_temp );
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.addop);
				binOpr.setLeftExp( expNode );
				ExpressionNode right = term( new ExpressionNode( lineNum ) ,synch_temp);
				binOpr.setRightExp(right);
				expNode = binOpr;
			}
		}
		printLeaveInfo( "addExp" );
		return expNode;
		
	}
	
	//28
		private ExpressionNode term( ExpressionNode node,SynchSet synch ) throws Exception {
			printEnterInfo( "term" );
			SynchSet synch_temp = new SynchSet();
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.multop);
			node = factor( new ExpressionNode( lineNum ),synch_temp );
			BinaryOperationNode binOpr = null;
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.multop);
			SynchCheck(synch_temp);
			while ( lookahead_In_FirstSet(NonterminalType.multop) ){
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.multop);
				synch_temp.union(NonterminalType.factor);
				BinaryOperationNode newBinOpr = new BinaryOperationNode( lineNum );
				multop(newBinOpr,synch_temp);
				synch_temp.clear();
				synch_temp.union(synch);
				synch_temp.union(NonterminalType.multop);
				ExpressionNode exp = factor( new ExpressionNode( lineNum ),synch_temp );
				if( binOpr == null ){
					//first meet multop
				//	binOpr = new BinaryOperationNode();
					newBinOpr.setLeftExp(node);
					newBinOpr.setRightExp( exp );
					binOpr = newBinOpr;
				}else{
					//meet multop more than once
					newBinOpr.setLeftExp( binOpr );
					newBinOpr.setRightExp( exp );
					binOpr = newBinOpr;
				}
				node = binOpr;
			}			
			printLeaveInfo( "term" );
			return node;
		}
		
		//29
		private ExpressionNode factor( ExpressionNode node ,SynchSet synch) throws Exception {
			printEnterInfo( "factor" );
			if( lookahead_In_FirstSet( NonterminalType.nidFactor )){ 
				node = nidFactor( new ExpressionNode( lineNum ),synch );
			}else if(lookahead_In_FirstSet(NonterminalType.idFactor)){
				node = idFactor( new IDFactorNode( lineNum ),synch );
			}		
			else{
				SynchError(synch,null);
			}
			printLeaveInfo( "factor" );
			return node;
		}
		
		//30
				private ExpressionNode nidFactor(ExpressionNode expressionNode,SynchSet synch) throws Exception {
					printEnterInfo( "nidFactor" );
					SynchSet synch_temp = new SynchSet();
					if( lookahead==TokenType.NOT ){	
						synch_temp.clear();
						synch_temp.union(synch);
						synch_temp.union(NonterminalType.factor);
						//determine it's a UnitaryOperationNode
						UnitaryOperationNode unitary = new UnitaryOperationNode( lineNum );
						//find operator
						unitary.setType( TokenType.BOOL );
						unitary.setOperator( TokenType.NOT );
						match( TokenType.NOT ,synch_temp);
						ExpressionNode exp = factor( new ExpressionNode( lineNum ) ,synch);
						unitary.setOperand( exp );
						//set return type
						expressionNode = unitary;
					}else if( lookahead==TokenType.LPAREN ){
						synch_temp.clear();
						synch_temp.union(synch);
						synch_temp.addTerminal(TokenType.RPAREN);
						synch_temp.union(NonterminalType.expression);
						match( TokenType.LPAREN ,synch_temp);
						synch_temp.clear();
						synch_temp.union(synch);
						synch_temp.addTerminal(TokenType.RPAREN);
						expressionNode = expression( new ExpressionNode( lineNum ) ,synch_temp);
						match( TokenType.RPAREN,synch );
					}else if( lookahead==TokenType.NUM ){
						LiteralNode var = new LiteralNode( lineNum );
						var.setValue(lookaheadValue);
						var.setType( TokenType.INT );
						match(TokenType.NUM,synch);
						expressionNode = var;
					}else if(lookahead == TokenType.BLIT){
						LiteralNode var = new LiteralNode( lineNum );
						var.setValue(lookaheadValue);
						var.setType( TokenType.BOOL );
						match( TokenType.BLIT,synch );
						expressionNode = var;
					}
					else{
						SynchError(synch,null);
					}
					printLeaveInfo( "nidFactor" );
					return expressionNode;
				}
		
		//31
		private IDFactorNode idFactor(IDFactorNode node,SynchSet synch) throws Exception {
			printEnterInfo( "idFactor" );
			SynchSet synch_temp = new SynchSet();
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.idTail);
			node.setIdentifier(lookaheadValue);
			match( TokenType.ID ,synch_temp);
			node = idTail( node,synch );
			printLeaveInfo( "idFactor" );
			return node;
		}

		//32
		private IDFactorNode idTail(IDFactorNode node,SynchSet synch) throws Exception {
			printEnterInfo( "idTail" );
			if( lookahead_In_FirstSet( NonterminalType.varTail )){
				VariableNode var = new VariableNode( node );
				varTail(var,synch);
				node = var;
			}else if( lookahead_In_FirstSet( NonterminalType.callTail )){
				CallNode call = new CallNode( node );
				callTail( call ,synch);
				node = call;
			}
			else{
				node = new VariableNode( node );
				SynchCheck(synch);
			}		
			printLeaveInfo( "idTail" );
			return node;
		}

		//33   Something To Be Discuss
		private void varTail( VariableNode var,SynchSet synch ) throws Exception {
			printEnterInfo( "varTail" );
			SynchSet synch_temp = new SynchSet();
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.union(NonterminalType.addExp);
			synch_temp.addTerminal(TokenType.RSQR);
			match( TokenType.LSQR ,synch_temp);
			synch_temp.clear();
			synch_temp.union(synch);
			synch_temp.addTerminal(TokenType.RSQR);
			ExpressionNode exp = addExp( new ExpressionNode( lineNum ) ,synch_temp);
			var.setIndex(exp);
			match( TokenType.RSQR,synch );
			printLeaveInfo( "varTail" );
		}
		
		//34
		private void relop( BinaryOperationNode node ,SynchSet synch) throws Exception {
			printEnterInfo( "relop" );
			if(lookahead==TokenType.LTEQ){
				node.setOperator( TokenType.LTEQ );
				node.setType( TokenType.BOOL );
				match( TokenType.LTEQ ,synch);
			}else if(lookahead == TokenType.LT ){
				node.setType( TokenType.BOOL );
				node.setOperator( TokenType.LT );
				match( TokenType.LT ,synch);
			}else if( lookahead == TokenType.GT ){
				node.setType( TokenType.BOOL );
				node.setOperator( TokenType.GT );
                match( TokenType.GT,synch);
			}else if( lookahead == TokenType.GTEQ ){
				node.setType( TokenType.BOOL );
				node.setOperator( TokenType.GTEQ );
				match( TokenType.GTEQ ,synch );
			}else if( lookahead == TokenType.EQ ){
				node.setType( TokenType.BOOL );
				node.setOperator( TokenType.EQ );
				match( TokenType.EQ ,synch);
			}else if(lookahead==TokenType.NEQ){
				node.setType( TokenType.BOOL );
				node.setOperator( TokenType.NEQ );
				match( TokenType.NEQ ,synch);
			}
			else{
				SynchError(synch,null);
			}
			printLeaveInfo( "relop" );
		}
	
	//35
	private void addop( BinaryOperationNode node,SynchSet synch ) throws Exception {
		printEnterInfo( "addop" );
		if( lookahead==TokenType.PLUS ){
			node.setOperator( TokenType.PLUS );
			node.setType( TokenType.INT );
			match( TokenType.PLUS,synch );
		}else if( lookahead == TokenType.MINUS ){
			node.setOperator( TokenType.MINUS );
			node.setType( TokenType.INT );
			match( TokenType.MINUS ,synch);
		}else if( lookahead ==TokenType.OR ){
			node.setOperator( TokenType.OR );
			node.setType( TokenType.BOOL );
			match( TokenType.OR ,synch);
		}else if(lookahead==TokenType.ORELSE){
			node.setOperator( TokenType.ORELSE );
			node.setType( TokenType.BOOL );
			match( TokenType.ORELSE ,synch);
		}else{
			SynchError(synch,null);
		}
		printLeaveInfo( "addop" );
	}
	
	//36
	private void multop( BinaryOperationNode node ,SynchSet synch) throws Exception {
		printEnterInfo( "multop" );
		if( lookahead==TokenType.MULT ){
			node.setOperator( TokenType.MULT );
			node.setType(TokenType.INT);
			match(TokenType.MULT,synch);
		}else if ( lookahead==TokenType.DIV ){
			node.setOperator( TokenType.DIV );
			node.setType(TokenType.INT);
			match(TokenType.DIV,synch);
		}else if( lookahead==TokenType.MOD){
			node.setOperator( TokenType.MOD );
			node.setType(TokenType.INT);
			match(TokenType.MOD,synch);
		}else if( lookahead==TokenType.AND ){
			node.setOperator( TokenType.AND );
			node.setType(TokenType.BOOL);
			match(TokenType.AND,synch);
		}else if(lookahead==TokenType.ANDTHEN){
			node.setOperator( TokenType.ANDTHEN );
			node.setType(TokenType.BOOL);
			match( TokenType.ANDTHEN ,synch);
		}else{
			SynchError(synch,null);
		}
		printLeaveInfo( "multop" );
	}
	
	
	
	//37
	private void uminus( UnitaryOperationNode node ,SynchSet synch) throws Exception {
		printEnterInfo( "uminus" );
		node.setOperator( TokenType.MINUS );
		node.setType( TokenType.INT );
		match( TokenType.MINUS ,synch);		
		printLeaveInfo( "uminus" );
	}

	/**
	 * @return get AST root to other components
	 */
	public ArrayList< DeclarationNode > getAstRoot() {
		return astRoot;
	}
}
